package com.yuan.fmmall.service.Impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yuan.fmmall.dao.UsersMapper;
import com.yuan.fmmall.entity.Users;
import com.yuan.fmmall.service.UserService;
import com.yuan.fmmall.utils.MD5Utils;
import com.yuan.fmmall.vo.ResStatus;
import com.yuan.fmmall.vo.ResultVO;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * @author Yuan
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    public UsersMapper usersMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Override
    public ResultVO checkLogin(String username, String pwd) {
        //日志打印
        logger.info(">>>"+new Date()+">用户："+username+"使用登录业务");
        //查询数据库操作
        Example example = new Example(Users.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username",username);
        List<Users> users = usersMapper.selectByExample(example);
        //得到查询结果，进行条件判断
        if(users.size()==0){
            return new ResultVO(ResStatus.NO,"用户名不存在",null);
        }else {
            //对传过来的密码进行md5加密后，再与数据库中的密码进行对比
            String md5Pwd = MD5Utils.md5(pwd);
            if (md5Pwd.equals(users.get(0).getPassword())){
                //密码正确，现在使用jwt来创建token
                JwtBuilder jwtBuilder = Jwts.builder();
                String token = jwtBuilder.setSubject(username)//主体，就是token中携带的数据
                        .setIssuedAt(new Date())//设置token生成时间
                        .setId(users.get(0).getUserId().toString())//设置用户id为token的id
                        .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000))//token过期时间，设置为一天
                        .signWith(SignatureAlgorithm.HS256, "Yuan")//设置加密方式和加密密码
                        .compact();
                //当用户登录成功后，以token为key，将用户信息保存到redis
                try {
                    //将数据转换为JSON格式，赋值给userInfo
                    String userInfo = objectMapper.writeValueAsString(users.get(0));
                    //存入token并设置过期时间30min， key： token，value： userInfo
                    stringRedisTemplate.boundValueOps(token).set(userInfo,30, TimeUnit.MINUTES);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                return new ResultVO(ResStatus.OK,token,users.get(0));
            }else {
                return new ResultVO(ResStatus.NO,"密码错误！",null);
            }
        }
    }

    @Override
    @Transactional
    public ResultVO userRegist(String name, String pwd) {
        //查询数据库
        Example example = new Example(Users.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username",name);
        List<Users> users = usersMapper.selectByExample(example);
        //判断该用户名是否已经被注册
        if(users.size()==0){
            //数据库中没有该用户名
            //对用户名密码进行md5加密
            String md5Pwd = MD5Utils.md5(pwd);
            //创建用户
            Users nu = new Users();
            nu.setUsername(name);
            nu.setPassword(md5Pwd);
            nu.setUserModtime(new Date());
            nu.setUserRegtime(new Date());
            //调用注册接口
            int flag = usersMapper.insert(nu);
            if(flag>0){
                return new ResultVO(10000,"注册成功！",nu);
            }else {
                return new ResultVO(10002,"注册失败！",null);
            }
        }else {
            //用户名已存在数据库中
            return new ResultVO(10001,"该用户名已经被注册！",null);
        }
    }
}
